package br.com.felinelayer.server;

import br.com.felinelayer.server.application.Application;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 */
public class Server implements Runnable, IApplicationFactory {

    private static ServerSocket socketServer;
    private int port = 7000;

    private Server() {
    }

    /**
     * @param args the command line arguments
     */
    public static void main( String[] args ) {
        runServer();
    }

    public static Server runServer() {
        Server server = new Server();
        try {
            new Thread( server ).start();
        } catch ( Exception ex ) {
            Logger.getLogger( Server.class.getName() ).log( Level.SEVERE, null, ex );
        }
        return server;
    }

    @Override
    public void run() {
        if ( socketServer == null ) {
            try {
                socketServer = new ServerSocket( port );
            } catch ( IOException ex ) {
                Logger.getLogger( Server.class.getName() ).log( Level.SEVERE, null, ex );
                return;
            }
        }
        // 
        System.out.println( "SERVER: waiting clients connection at port " + port );
        try {
            // Loop to wait new connections
            while ( true ) {
                // Wait new connections
                Socket socket = socketServer.accept();
                // When client conects then runs statement
                System.out.println( "SERVER: client connected!" );
                // Create client
                ClientServer client = new ClientServer( socket );
                // Execute application thread
                new ApplicationLauncher( this, client ).start();
            }
        } catch ( IOException ex ) {
            Logger.getLogger( Server.class.getName() ).log( Level.SEVERE, null, ex );
        }
    }

    /**
     * Application factory
     *
     * @param applicationName
     * @return Application
     */
    @Override
    public synchronized Application createApplicationByName( String applicationName ) {
        try {
            Object o = getClass().getClassLoader().loadClass( applicationName ).newInstance();
            if ( o instanceof Application ) {
                return (Application) o;
            }
        } catch ( InstantiationException | IllegalAccessException | ClassNotFoundException ex ) {
            Logger.getLogger( Server.class.getName() ).log( Level.SEVERE, null, ex );
        }
//        if ( applicationName.equalsIgnoreCase( "sample" ) )
//            return new Sample();
        return null;
    }
}
